package brwarner.game 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Point;
	import brwarner.game.states.GridState;
	import brwarner.game.GameConstants;
	/**
	 * ...
	 * @author Brook Jensen
	 */
	public class Humans extends EventDispatcher
	{
		//Amount of money currently in the bank
		private var _funds:Number;
		
		//Last recorded population
		private var _lastPop:Number;
		
		//Update listener
		public static const THINK_EVENT = "onHumanThink";
		
		public function Humans() 
		{
			_funds  = GameConstants.INITIAL_FUNDS;
			_lastPop = 0;
		}
		
		//Gets the current level of funds
		public function get Funds( ):Number { return _funds; }
		public function get Population( ):Number { return _lastPop; }
		
		//Infects the tile
		private function infect( tile:Point, grid:GameGrid )
		{
			//Check if we hae enough money to build
			if ( Funds >= GameConstants.BUILD_COSTS[ grid.getTile( tile ).Type ] )
			{
				grid.getTile( tile ).Infection = GridSquare.HUMAN_CITY;
				_funds -= GameConstants.BUILD_COSTS[ grid.getTile(tile).Type ];
			}
		}
		
		//Gets surrounding squares (warning, may include duplicates)
		public function getSurrounding( infected:Array, grid:GameGrid )
		{
			//Result
			var surrounding:Array = new Array();
			
			//For each infected square
			for ( var i = 0; i < infected.length; i++ )
			{
				//THis point
				var p:Point = infected[i] as Point;
				
				//Check surrounding squares
				if ( p.x > 0 && !grid.getTile( new Point( p.x - 1, p.y ) ).Infected )
					surrounding.push( new Point( p.x - 1, p.y ) );
				if ( p.x < GameConstants.GRID_SIZE - 1 && !grid.getTile( new Point( p.x + 1, p.y ) ).Infected )
					surrounding.push( new Point( p.x + 1, p.y ) );
				if ( p.y > 0 && !grid.getTile( new Point( p.x, p.y - 1 ) ).Infected )
					surrounding.push( new Point( p.x, p.y - 1 ) );
				if ( p.y < GameConstants.GRID_SIZE - 1 && !grid.getTile( new Point( p.x, p.y + 1) ).Infected )
					surrounding.push( new Point( p.x, p.y + 1 ) );
			}
			
			return surrounding;
		}
		
		//Called to allow the humans to think
		public function think( infected:Array, grid:GameGrid )
		{
			grid.Block = true;
			
			//Figure out the total population of the race
			var pop:Number = 0;
			for ( var i = 0; i < infected.length; i++ )
			{
				var tile:GridSquare = grid.getTile( infected[i] as Point );
				if ( tile.Infection == GridSquare.HUMAN_BASE ) continue;
				pop += tile.Population;
				
				//Grow population
				tile.Population += Math.ceil(tile.Population * GameConstants.GROWTH_RATE[ tile.Level ]);
			}
			
			//Calculate new funds
			_funds += pop * GameConstants.MONEY_PER_CAPITA;
			
			//Estimate population
			_lastPop = pop;
			
			//Get the surrounding squares
			var surrounding:Array = getSurrounding( infected, grid );
			
			//Find the one of lowest cost
			var minCost:Number = Number.MAX_VALUE, minPoint:Point = new Point( -1, -1);
			for ( var i = 0; i < surrounding.length; i++ )
			{
				var p:Point = surrounding[i] as Point;
				if ( grid.getTile( p ).Type >= GameConstants.BUILD_COSTS.length ) continue;
				var c:Number = GameConstants.BUILD_COSTS[grid.getTile( p ).Type];
				if ( grid.getTile( p ).Type == GridSquare.TOWER ) {
					minCost = 0;
					minPoint = p;
				}
				if ( c < minCost && c != -1 ) {
					minCost = c;
					minPoint = p;
				}
			}
			if ( minCost != Number.MAX_VALUE )
			{
				infect( minPoint, grid );
				if ( grid.getTile( minPoint ).Type == GridSquare.TOWER ) {
					grid.endGame();
				}
			}
			dispatchEvent( new Event( THINK_EVENT ) );
			grid.refreshSprites();
			
			grid.Block = false;
		}
		
	}

}